/*!
 * 基础类，包含常用类的一些方法
 * @author: __author__
 * @version: __buildVersion__
 * @buildDate：__buildDate__
 */
export let version: string = '__buildVersion__';
import { merge2 } from 'aiv367-merge';

interface I_BaseClassPlugin {
    (base: Base): void
}

interface I_BaseClassEventFun {
    (evt: I_BaseClassEventData, data?: any): void;
}

interface I_BaseClassEvent {
    fn: I_BaseClassEventFun;
    fnKey: string;
}

interface I_BaseClassEvents {
    [eventName: string]: I_BaseClassEvent[];
}

interface I_BaseClassEventData {
    type: string,
    instance: Base,
    [propName: string]: any
}

export default class Base {

    protected _events: I_BaseClassEvents = {};
    protected _datas: any = {};
    protected _opts: any = {};

    constructor(..._args: any) {}

    /** 设置，返回数据 */
    public data(key?: string, value?: any) {
        if (key !== undefined && value !== undefined) { // 设置值
            this._datas[key] = value;
        } else if (key !== undefined && value === undefined) {// 获取值
            return this._datas[key];
        } else if (key === undefined && value === undefined) {// 获取全部值
            return this._datas;
        }
    }

    /** 设置，返回参数 */
    public option(opts?: any): any {
        merge2(this._opts, opts);
        return this._opts;
    }

    /** 扩展类 */
    public use(plugin: I_BaseClassPlugin): void {
        if (typeof plugin === 'function') {
            plugin.bind(this)(this);
        }
    }

    /** 绑定事件 */
    public on(eventName: string, fn: I_BaseClassEventFun, fnKey = ''): void {

        // type 转数组 去重 + 过滤
        let eventNames: string[] = [
            ...new Set(eventName.trim().replace(/ +/gi, ' ').split(' ')),
        ];

        eventNames.forEach((eventName: string) => {
            if (!this._events[eventName]) {
                this._events[eventName] = [];
            }
            this._events[eventName].push({ fn, fnKey });
        });

    }

    /** 绑定一次事件 */
    public one(eventName: string, fn: I_BaseClassEventFun, fnKey = ''): void {

        let fnOne: I_BaseClassEventFun = (evt: I_BaseClassEventData, data?: any) => {
            fn(evt, data);
            this.off(eventName, fnOne);
        }

        this.on(eventName, fnOne, fnKey);

    }

    /** 移除事件 fnOrFnKey 可以是 function 或者 string = fnKey */
    public off(eventName: string, fnOrFnKey?: I_BaseClassEventFun | string): void {
        let events = this._events[eventName];
        if (events) {
            if (fnOrFnKey !== undefined) {
                for (let i = events.length - 1; i >= 0; i--) {
                    let event = events[i];
                    if (event.fn === fnOrFnKey || event.fnKey === fnOrFnKey) {
                        this._events[eventName].splice(i, 1);
                    }
                }
            } else {
                delete this._events[eventName];
            }
        }
    }

    /** 触发事件 */
    public trigger(eventName: string, data?: any): void {
        this._events[eventName]?.forEach(evt => {
            let eventData: I_BaseClassEventData = {
                type: eventName,
                instance: this,
            };
            evt.fn.bind(this)(eventData, data);
        });
    }

}